package com.sinosoft.listener;

//import javafx.beans.property.ListProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.env.PropertySourceLoader;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.*;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.web.context.support.ServletRequestHandledEvent;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;

/** 自定义加载文件
 * @Auther: zouren
 * @Date: 2019/3/8 15:26
 * @Description:
 */
public class AutoConfigListener implements ApplicationListener<ApplicationEvent> {
    private Logger logger = LoggerFactory.getLogger(getClass());
    private  final ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        if(applicationEvent instanceof ServletRequestHandledEvent){
            logger.info("监听请求信息: { }"+applicationEvent.toString());
        }else if (applicationEvent instanceof ApplicationEnvironmentPreparedEvent){
            readConfig((ApplicationEnvironmentPreparedEvent)applicationEvent);
        }
    }

    private void readConfig(ApplicationEnvironmentPreparedEvent applicationEvent) {
        logger.debug("read config start");
        ConfigurableEnvironment environment=  applicationEvent.getEnvironment();
        String[] activeProfiles = environment.getActiveProfiles();
        List<PropertySourceLoader> propertySourceLoaderList = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class,getClass().getClassLoader());
        logger.info("activeProfiles:{}",activeProfiles.length>=1?activeProfiles[0]:"no activeProfiles");
        readFile(environment, activeProfiles, propertySourceLoaderList);
        logger.debug("read config end");
    }

    /**
     * 读取配置文件
     * @param environment
     * @param activeProfiles
     * @param propertySourceLoaderList
     */
    private void defaultReadFile(ConfigurableEnvironment environment, String[] activeProfiles, List<PropertySourceLoader> propertySourceLoaderList) {
        Arrays.stream(activeProfiles).forEach(activeProfile -> propertySourceLoaderList.stream().forEach(loader ->
                Arrays.stream(loader.getFileExtensions()).forEach(fileExtension -> {
                            try {
                                if("yml".equals(fileExtension)||"properties".equals(fileExtension)){
                                    Resource[] resources = resourcePatternResolver.getResources(activeProfile+"/*."+fileExtension);
                                    Arrays.stream(resources).forEach(resource->{
                                        try {
                                            logger.debug("resource={}",resource.toString());
                                            List<PropertySource<?>> propertySources1ist = loader.load(resource.getFilename(),resource);
                                            if(propertySources1ist!=null&&propertySources1ist.size()>=1){
                                                propertySources1ist.stream().forEach(environment.getPropertySources()::addLast);
                                            }
                                        } catch (IOException e) {
                                            logger.error("activeProfile={} , fileExtension={} e={}",activeProfile,fileExtension,e.getMessage());
                                        }
                                    });
                                }
                            } catch (IOException e) {
                                logger.error("activeProfile={} , fileExtension={} e={}",activeProfile,fileExtension,e.getMessage());
                            }
                        }
                )));
    }

    /**
     * 读取配置文件 增加 读入与jar包同级中config中的文件
     * @param environment
     * @param activeProfiles
     * @param propertySourceLoaderList
     */
    private void readFile(ConfigurableEnvironment environment, String[] activeProfiles, List<PropertySourceLoader> propertySourceLoaderList) {
        URL classUrl = Thread.currentThread().getContextClassLoader().getResource("");
        File file = new File(classUrl.toString());
        String parentPath = file.getParent()+"/config/";
        Arrays.stream(activeProfiles).forEach(activeProfile -> propertySourceLoaderList.stream().forEach(loader ->
                Arrays.stream(loader.getFileExtensions()).forEach(fileExtension -> {
                            try {
                                if("yml".equals(fileExtension)||"properties".equals(fileExtension)){
                                    Resource[] resources = new Resource[0];
                                    try {
                                        logger.info("default loading:"+activeProfile+"/*."+fileExtension);
                                        resources = resourcePatternResolver.getResources(activeProfile+"/*."+fileExtension);

                                    } catch (Exception e) {
                                        logger.info("file loading:"+parentPath+activeProfile+"/*."+fileExtension);
                                        resources = resourcePatternResolver.getResources(parentPath+activeProfile+"/*."+fileExtension);
                                    }
                                    Arrays.stream(resources).forEach(resource->{
                                        try {
                                            logger.debug("resource={}",resource.toString());
                                            List<PropertySource<?>> propertySources1ist = loader.load(resource.getFilename(),resource);
                                            if(propertySources1ist!=null&&propertySources1ist.size()>=1){
                                                propertySources1ist.stream().forEach(environment.getPropertySources()::addLast);
                                            }
                                        } catch (IOException e) {
                                            logger.error("activeProfile={} , fileExtension={} e={}",activeProfile,fileExtension,e.getMessage());
                                        }
                                    });
                                }
                            } catch (IOException e) {
                                logger.error("activeProfile={} , fileExtension={} e={}",activeProfile,fileExtension,e.getMessage());
                            }
                        }
                )));
    }

}
